#include <pin_name.h>
#include "drv_gpio.h"
#include "phy.h"
#include <soc.h>
#include <aos/kernel.h>
#include "k_api.h"
#include "ethernetif.h"
#include "lwip/etharp.h"
#include "lwip/tcpip.h"
#include "lwip/netifapi.h"
#include "ntp.h"
#include "cx_cloud.h"
#include "iot_import.h"
#include "aogpio.h"
#include "ulog/ulog.h"

#define TAG "GMAC"

#define TCPIP_INIT  "tcpip_init_task"

/*Static IP ADDRESS*/
#ifndef IP_ADDR0
#define IP_ADDR0   192
#define IP_ADDR1   168
#define IP_ADDR2   1
#define IP_ADDR3   80
#endif
/*NETMASK*/
#ifndef NETMASK_ADDR0
#define NETMASK_ADDR0   255
#define NETMASK_ADDR1   255
#define NETMASK_ADDR2   255
#define NETMASK_ADDR3   0
#endif
/*Gateway Address*/
#ifndef GW_ADDR0
#define GW_ADDR0   192
#define GW_ADDR1   168
#define GW_ADDR2   1
#define GW_ADDR3   1
#endif

// #define GMAC_TEST
void *cxcloud_hdl;

void cx_cloud_task(void *arg)
{
    char product_key[PRODUCT_KEY_LEN + 1];
    char device_name[DEVICE_NAME_LEN + 1];
    char device_secret[DEVICE_SECRET_LEN + 1];
    char product_secret[PRODUCT_SECRET_LEN + 1];
    int log_level = CX_CLOUD_LOG_WARN;//默认debug日志级别

    while(1) {
		if(ntp_sync_time(NULL) == 0) {
            break;
        }
        aos_msleep(1000);
    }

    if ((0 == HAL_GetProductKey(product_key)) || (0 == HAL_GetProductSecret(product_secret)) ||
        (0 == HAL_GetDeviceSecret(device_secret)) || (0 == HAL_GetDeviceName(device_name))) {
        printf("!!!!!! missing ProductKey/ProductSecret/DeviceName/DeviceSecret\n");
        return;
    }

    cx_cloud_param_t param;
    param.dev_id = 0;
    param.device_name = device_name;
    param.device_secret = device_secret;
    param.product_key = product_key;
    param.product_secret = product_secret;
    param.log_level = log_level;

    cxcloud_hdl = cx_cloud_init(&param, NULL);
    cx_cloud_connect(cxcloud_hdl);
    aos_task_exit(0);
}

struct netif xnetif; /* network interface structure */

void net_status_callback(struct netif *netif)
{
    aos_task_t ntp_handle;
    if (!ip_addr_isany(ip_2_ip4(&netif->ip_addr))) {
        // event_publish(EVENT_NET_GOT_IP, NULL);
		LOGD(TAG, "IP address: %s", ipaddr_ntoa((ip4_addr_t *)ip_2_ip4(&netif->ip_addr)));
        LOGD(TAG, "Subnet mask: %s", ipaddr_ntoa((ip4_addr_t *)ip_2_ip4(&netif->netmask)));
        LOGD(TAG, "Default gateway:  %s", ipaddr_ntoa((ip4_addr_t *)ip_2_ip4(&netif->gw)));
        aos_task_new_ext(&ntp_handle, "cx_cloud_task", cx_cloud_task, NULL, 8192, AOS_DEFAULT_APP_PRI + 10);
    }
    
    LOGD(TAG, "app fota start");
    extern void app_fota_start(void);
	app_fota_start();
}

void tcpip_init_server(void *paras)
{
	ip_addr_t ipaddr;
    ip_addr_t netmask;
    ip_addr_t gw;
    int8_t idx = 0;
    /* Create tcp_ip stack thread */
    tcpip_init(NULL, NULL);

	IP4_ADDR(&ipaddr, IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3);
	IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
	IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);


	xnetif.name[0] = 'r';
	xnetif.name[1] = '0' + idx;
	netif_add(&xnetif, &ipaddr, &netmask, &gw, NULL, ethernetif_init_gmac, tcpip_input);

    /*  Registers the default network interface. */
    netif_set_default(&xnetif);

    /*  When the netif is fully configured this function must be called.*/
	netif_set_link_up(&xnetif);
	netif_set_up(&xnetif);
    netif_set_flags(&xnetif, NETIF_FLAG_IGMP);

	// netif_set_ipaddr(&xnetif, NULL);
    // netif_set_netmask(&xnetif, NULL);
    // netif_set_gw(&xnetif[0], NULL);
	netif_set_status_callback(&xnetif, net_status_callback);
    LOGD(TAG, "DHCP start");
	netifapi_dhcp_start(&xnetif);
    aos_task_exit(0);
}

int gmac_sw_init(void)
{
    int ret = 0;
    aos_task_t tcpip_init_handle;

    ret = aos_task_new_ext(&tcpip_init_handle, TCPIP_INIT, tcpip_init_server, NULL, 5120, AOS_DEFAULT_APP_PRI);
    if (RHINO_SUCCESS != ret) {
        printf(TCPIP_INIT "create fail!\n");
        return -1;
    }
	return ret;
}

#define PHY88E1111_RESET_PIN            PA23

typedef struct eth_phy_config{
    uint32_t phy_addr;
    phy_if_mode_t interface;
}eth_phy_config_t;

extern eth_phy_config_t sg_eth_phy_config[CONFIG_ETH_PHY_NUM];
void board_phy88e1111_init(void)
{
    gpio_pin_handle_t pin = NULL;
    
    extern int32_t drv_pinmux_usi_nss_ctrl_type_config(Usi_index_t usi_index,Usi_nss_ctrl_type_t nss_ctrl_type);
    drv_pinmux_usi_nss_ctrl_type_config(USI_INDEX_0, GPIO_CTRL);
    pin = csi_gpio_pin_initialize(PHY88E1111_RESET_PIN, NULL);
    csi_gpio_pin_config_direction(pin, GPIO_DIRECTION_OUTPUT);
    csi_gpio_pin_write(pin, 0);
    aos_msleep(20);
    csi_gpio_pin_write(pin, 1);

    sg_eth_phy_config[0].interface = PHY_IF_MODE_GMII;
}

int gmac_hw_init(void)
{
    board_phy88e1111_init();

    extern int csi_eth_mac_phy_init(void);
    csi_eth_mac_phy_init();

    return 0;
}

static void gmac_init_func(void *paras)
{
    // LOGD(TAG, "gmac init");
    gmac_hw_init();
    LOGD(TAG, "gmac_hw init over");
#ifdef GMAC_TEST
    extern int test_gmac(void);
    test_gmac();
#else   
    gmac_sw_init();
#endif
    aos_task_exit(0);
}

void gmac_init(void)
{
    int ret;
    aos_task_t gmac_hdl;
    ret = aos_task_new_ext(&gmac_hdl, "gmac_init", gmac_init_func, NULL, 1024, AOS_DEFAULT_APP_PRI+1);
    if (RHINO_SUCCESS != ret) {
        printf("gmac_init task create fail!\n");
    }
}